#include "common.hpp"

static const char *optString = "r:h?";

static const struct option longOpts[] = {
	{ "help", no_argument, NULL, 'h' },
//	{ "index", required_argument, NULL, 'i' },
	{ "resource", required_argument, NULL, 'r' },
	{ 0,0,0,0 }
};

int main (int argc, char* const argv[]) {
	srand( time(NULL) + getpid() );

	ipc::shared_memory_with_exceptions<size_t> listas	( my_ftok(COUNTER|LISTAS));

	ipc::semaphore_with_exceptions mutex_listas ( my_ftok(MUTEX|LISTAS),0);

	ipc::semaphore_with_exceptions mutex_etiquetadora ( my_ftok(MUTEX|ETIQUETADORA),0);

	ipc::messages_queue_with_exceptions tapadora_salida ( my_ftok(MSG_QUEUE|TAPADORA) );
//	ipc::messages_queue_with_exceptions etiquetadora_salida ( my_ftok(MSG_QUEUE|ETIQUETADORA) );

	int longIndex = 0;
	int option = 0;
	bool ayuda = false;
	size_t procesadas = 0;
	long etiquetas = 0;

	// Interpretación de parametros.
	while ( (option = getopt_long(argc,argv,optString,longOpts,&longIndex) ) != EOF ) {
		switch (option) {
			case '?':
			case 'h':
			case ':':
				ayuda = true;
				break;
			case 'r':
				etiquetas = parse<long>(optarg,-1);
			default:
				break;
		}
	}

	if ( ayuda || etiquetas < 0) {
		std::cerr << "Proceso de control de un brazo con una etiquetadora de botellas tapadas." << std::endl;
		std::cerr << "\tUso: " << argv[0] << " [-h] [-r natural]" << std::endl;
		std::cerr << "\tParametros:" << std::endl;
		std::cerr << "\t\t-h,--help:\tMostrar este mensaje de ayuda." << std::endl;
		std::cerr << "\t\t-r,--resource:\tNúmero de etiquetas disponibles en la estación." << std::endl;

		return (ayuda) ? 0 : -1;
	}

	try {
		listas.get(PERMITS);

		mutex_listas.get(PERMITS);

		mutex_etiquetadora.get(PERMITS);

		tapadora_salida.get(PERMITS);

		sBotella entrante;		

		logger << "Estación de etiquetado: Inicio." << nl;
		procesadas = 0;
		while (etiquetas > 0) {
			entrante.tipo = CUALQUIERA;
			mutex_etiquetadora.wait();

			tapadora_salida.receive(entrante,SBOTELLA_TIPO);

			if ( (entrante.tipo == SBOTELLA_TIPO) && (entrante.estado == TAPADA) ) {
				etiquetas--;
				logger << "Estación de etiquetado: Etiquetando botella " << procesadas+1 << "." << nl;
				// tapar botella.
				usleep ( rand()%1000 + 200 );

				// Enviar botella llena a la siguiente estación.
				mutex_listas.wait();
					(*listas)++;
					procesadas++;
					logger << "Estación de etiquetado: Botella etiquetada " << procesadas << nl;
				mutex_listas.signal();

				// Solo libero la llenadora si aun quedaban botellas cuando 
			} else {
				error << "Estación de etiquetado: Botella incorrecta en la maquina." << nl;
			}
			mutex_etiquetadora.signal();
		} // while (etiquetas > 0)
		logger << "Estación de etiquetado: detenida por falta de etiquetas." << nl;

	} catch (ipc::exception& e) {
		logger << "Estacion de etiquetado: " << e.what() << "." << nl;
		exit(-1);
	}
	logger << "Estación de etiquetado: Fin." << nl;
	return 0;
}
